package com.wpen.unit.service.job.impl;

import java.sql.Timestamp;
import java.util.Date;
import java.util.List;

import com.wpen.unit.service.job.BatchInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.wpen.unit.AppVariables;
import com.wpen.unit.core.cache.CacheDatas;
import com.wpen.unit.cron.CronUtil;
import com.wpen.unit.cvt.job.BatchInfoCvt;
import com.wpen.unit.enums.DependType;
import com.wpen.unit.enums.YN;
import com.wpen.unit.exception.BizException;
import com.wpen.unit.infra.mybatis.job.po.BatchInfoPo;
import com.wpen.unit.infra.mybatis.job.po.BatchPlanPo;
import com.wpen.unit.infra.mybatis.job.po.DependonPo;
import com.wpen.unit.infra.repository.job.BatchInfoRepository;
import com.wpen.unit.infra.repository.job.BatchPlanRepository;
import com.wpen.unit.infra.repository.job.DependonRepository;
import com.wpen.unit.utils.DateUtil;
import com.wpen.unit.utils.SpringUtil;
import com.wpen.unit.web.dto.job.BatchInfoAddRequest;
import com.wpen.unit.web.dto.job.BatchInfoAddResponse;
import com.wpen.unit.web.dto.job.BatchInfoEnableRequest;
import com.wpen.unit.web.dto.job.BatchInfoEnableResponse;
import com.wpen.unit.web.dto.job.BatchInfoListRequest;
import com.wpen.unit.web.dto.job.BatchInfoListResponse;
import com.wpen.unit.web.dto.job.BatchInfoListRowsResponse;
import com.wpen.unit.web.dto.job.BatchInfoModRequest;
import com.wpen.unit.web.dto.job.BatchInfoModResponse;
import com.wpen.unit.web.dto.job.BatchInfoNextTimeRequest;
import com.wpen.unit.web.dto.job.BatchInfoNextTimeResponse;
import com.wpen.unit.web.dto.job.StatRequest;
import com.wpen.unit.web.dto.job.StatResponse;

@Service
public class BatchInfoServiceImpl implements BatchInfoService {

	@Autowired
	private BatchInfoRepository batchInfoRepository;
	@Autowired
	private BatchPlanRepository batchPlanRepository;
	@Autowired
	private CacheDatas cacheDatas;
	@Autowired
	private DependonRepository dependonRepository;

	@Override
	public BatchInfoListResponse queryListBatchInfo(BatchInfoListRequest batchInfoListRequest) {
		int index = batchInfoListRequest.getIndex();
		int size = batchInfoListRequest.getSize();
		// 数据库查询
		BatchInfoPo batchInfoPo = BatchInfoCvt.INSTANCE.queryListDto2Do(batchInfoListRequest);

		long total = batchInfoRepository.count(batchInfoPo);
		List<BatchInfoPo> batchInfoPoLists = batchInfoRepository.queryList(index, size, batchInfoPo);

		// 返回响应信息
		BatchInfoListResponse batchInfoListResponse = new BatchInfoListResponse();
		batchInfoListResponse.setTotal(total);
		batchInfoListResponse.setCount(0);
		if (batchInfoPoLists != null) {
			batchInfoListResponse.setCount(batchInfoPoLists.size());
			List<BatchInfoListRowsResponse> listRows = batchInfoListResponse.getRows();
			for (BatchInfoPo inBatchInfoPo : batchInfoPoLists) {
				BatchInfoListRowsResponse row = BatchInfoCvt.INSTANCE.queryListRowDo2Dto(inBatchInfoPo);
				row.setCreateTime(inBatchInfoPo.getCreateTime());
				row.setUpdateTime(inBatchInfoPo.getUpdateTime());
				listRows.add(row);
			}
			batchInfoListResponse.setRows(listRows);
		}

		return batchInfoListResponse;
	}

	@Override
	@Transactional
	public BatchInfoAddResponse addBatchInfo(BatchInfoAddRequest batchInfoAddRequest) {
		// 持久化操作
		BatchInfoPo batchInfoPo = BatchInfoCvt.INSTANCE.addDto2Do(batchInfoAddRequest);
		batchInfoPo.setEnabled(YN.No.value());
		batchInfoPo.setCreateTime(new Date());
		batchInfoPo.setVersion(1);
		// batchInfoPo.setTimeStamp(new Date());

		// 测试cron是否正确
		CronUtil.getTime(batchInfoPo.getScheduleConf(), new Date());
		// 保存数据
		batchInfoRepository.insert(batchInfoPo);

		BatchPlanPo batchPlanPo = new BatchPlanPo();
		batchPlanPo.setId(batchInfoPo.getId());
		batchPlanPo.setBizCode(batchInfoPo.getBizCode());
		batchPlanPo.setBatchCode(batchInfoPo.getBatchCode());
		batchPlanPo.setPlanType(batchInfoPo.getScheduleType());
		batchPlanPo.setEnabled(YN.No.value());
		batchPlanPo.setTriggerLastTime(0L);
		batchPlanPo.setTriggerNextTime(0L);
		batchPlanPo.setCreateTime(new Date());
		batchPlanRepository.insert(batchPlanPo);

		// 添加依赖关系，
		DependonPo batchDpdPo = new DependonPo();
		// B-批次，T-任务，J-任务作业
		batchDpdPo.setSelfType(DependType.Batch.value());
		batchDpdPo.setBizCode(batchInfoPo.getBizCode());
		batchDpdPo.setBatchCode(batchInfoPo.getBatchCode());
		batchDpdPo.setTaskCode(AppVariables.DEPENDON_PHD);
		batchDpdPo.setJobCode(AppVariables.DEPENDON_PHD);
		batchDpdPo.setDpdonBizCode(AppVariables.DEPENDON_PHD);
		batchDpdPo.setDpdonBatchCode(AppVariables.DEPENDON_PHD);
		batchDpdPo.setDpdonTaskCode(AppVariables.DEPENDON_PHD);
		batchDpdPo.setDpdonJobCode(AppVariables.DEPENDON_PHD);
		DependonPo dependonPoDb = dependonRepository.queryFirst(batchDpdPo);
		if (dependonPoDb == null) {
			batchDpdPo.setEnabled(YN.Yes.value());
			batchDpdPo.setCreateTime(new Date());
			dependonRepository.insert(batchDpdPo);
		}

		// 返回响应信息
		BatchInfoAddResponse batchInfoAddResponse = new BatchInfoAddResponse();
		return batchInfoAddResponse;
	}

	@Override
	@Transactional
	public BatchInfoModResponse modBatchInfo(BatchInfoModRequest batchInfoModRequest) {
		// 持久化操作
		BatchInfoPo batchInfoPo = BatchInfoCvt.INSTANCE.modDto2Do(batchInfoModRequest);
		// 查询数据是否存在
		BatchInfoPo batchInfoPoDb = batchInfoRepository.queryById(batchInfoPo.getId());
		if (batchInfoPoDb == null) {
			throw new BizException("E00001", batchInfoModRequest.getId() + "");
		}
		// 测试cron是否正确
		CronUtil.getTime(batchInfoPo.getScheduleConf(), new Date());
		// 清理缓存
		cacheDatas.removeBatchInfoById(batchInfoPoDb.getId());

		// 更新数据
		batchInfoPo.setId(batchInfoPoDb.getId());
		batchInfoPo.setVersion(batchInfoPoDb.getVersion());
		// batchInfoPo.setTimeStamp(batchInfoPoDb.getTimeStamp());
		batchInfoRepository.updateById(batchInfoPo);
		// 重新更新plan表下次触发时间

		BatchPlanPo batchPlanPo = new BatchPlanPo();
		batchPlanPo.setId(batchInfoPo.getId());
		Date nextTime = CronUtil.getTime(batchInfoPo.getScheduleConf(), new Date());
		batchPlanPo.setTriggerNextTime(nextTime.getTime());
		batchPlanPo.setUpdateTime(new Timestamp(new Date().getTime()));
		batchPlanRepository.updateById(batchPlanPo);

		// 清理缓存
		cacheDatas.removeBatchInfoById(batchInfoPoDb.getId());
		// 返回响应信息
		BatchInfoModResponse batchInfoModResponse = new BatchInfoModResponse();
		return batchInfoModResponse;
	}

	@Transactional
	public String ableBatchInfo2(BatchInfoPo batchInfoPo) {
		BatchPlanPo batchPlanPo = batchPlanRepository.queryById(batchInfoPo.getId());
		String toEnable = null;
		if (YN.Yes.value().equals(batchInfoPo.getEnabled())) {
			toEnable = YN.No.value();
		} else {
			toEnable = YN.Yes.value();
		}
		BatchInfoPo upBatchInfoPo = new BatchInfoPo();
		upBatchInfoPo.setId(batchInfoPo.getId());
		upBatchInfoPo.setVersion(batchInfoPo.getVersion());
		upBatchInfoPo.setEnabled(toEnable);
		batchInfoRepository.updateById(upBatchInfoPo);

		if (batchPlanPo == null) {
			// 更新状态，插入计划
			batchPlanPo = new BatchPlanPo();
			batchPlanPo.setId(batchInfoPo.getId());
			batchPlanPo.setBizCode(batchInfoPo.getBizCode());
			batchPlanPo.setPlanType(batchInfoPo.getScheduleType());
			batchPlanPo.setEnabled(toEnable);
			batchPlanPo.setTriggerLastTime(0L);
			Date nextTime = CronUtil.getTime(batchInfoPo.getScheduleConf(), new Date());
			batchPlanPo.setTriggerNextTime(nextTime.getTime());
			batchPlanRepository.insert(batchPlanPo);
		} else {
			// 更新
			batchPlanPo.setId(batchInfoPo.getId());
			batchPlanPo.setEnabled(toEnable);
			batchPlanPo.setPlanType(batchInfoPo.getScheduleType());
			if (YN.Yes.value().equals(toEnable)) {
				batchPlanPo.setTriggerLastTime(batchPlanPo.getTriggerNextTime());
				Date nextTime = CronUtil.getTime(batchInfoPo.getScheduleConf(), new Date());
				batchPlanPo.setTriggerNextTime(nextTime.getTime());
			} else {
				batchPlanPo.setTriggerLastTime(batchPlanPo.getTriggerNextTime());
				batchPlanPo.setTriggerNextTime(0L);
			}
			batchPlanRepository.updateById(batchPlanPo);
		}
		return toEnable;
	}

	@Override
	public BatchInfoEnableResponse ableBatchInfo(BatchInfoEnableRequest batInfoEnableRequest) {
		Long id = batInfoEnableRequest.getId();
		// 查询数据是否存在
		BatchInfoPo batchInfoPo = batchInfoRepository.queryById(id);
		if (batchInfoPo == null) {
			throw new BizException("E00001", id);
		}
		// 测试cron是否正确
		CronUtil.getTime(batchInfoPo.getScheduleConf(), new Date());
		// 缓存清理
		cacheDatas.removeBatchInfoById(id);
		// 维护状态的启动/停止，同步维护2个表。
		String toEnable = SpringUtil.getBean(this.getClass()).ableBatchInfo2(batchInfoPo);

		BatchInfoEnableResponse response = new BatchInfoEnableResponse();
		response.setEnabled(toEnable);
		return response;
	}

	@Override
	public BatchInfoNextTimeResponse nextTimeBatchInfo(BatchInfoNextTimeRequest batchInfoNextTimeRequest) {
		String bizCode = batchInfoNextTimeRequest.getBizCode();
		String batchCode = batchInfoNextTimeRequest.getBatchCode();
		// 查询数据是否存在
		BatchInfoPo batchInfoPo = batchInfoRepository.queryByCode(bizCode, batchCode);
		if (batchInfoPo == null) {
			throw new BizException("E00001", bizCode + "-" + batchCode);
		}
		BatchInfoNextTimeResponse response = new BatchInfoNextTimeResponse();
		List<String> nexts = response.getNextTimes();
		Date date = new Date();
		for (int i = 0; i < 5; i++) {
			Date next = CronUtil.getTime(batchInfoPo.getScheduleConf(), date);
			nexts.add(DateUtil.format(next, DateUtil.FORMAT_DATETIME));
			date = next;
		}
		return response;
	}

	@Override
	public StatResponse statCountBatch(StatRequest statRequest) {
		StatResponse statResponse = new StatResponse();
		BatchInfoPo batchInfoPo = new BatchInfoPo();
		long count = batchInfoRepository.count(batchInfoPo);
		statResponse.setCount(count);
		batchInfoPo.setEnabled(YN.Yes.value());
		long alive = batchInfoRepository.count(batchInfoPo);
		statResponse.setAlive(alive);
		return statResponse;
	}

}
